package com.codedog.fx;

import cn.hutool.extra.spring.SpringUtil;
import com.codedog.constant.BeanNameConstant;
import com.codedog.constant.OptionConstant;
import com.codedog.constant.WindowSizeConstant;
import com.codedog.constant.WindowTextConstant;
import com.codedog.controller.CodeDogController;
import com.codedog.controller.ShutdownController;
import com.codedog.enums.ResponseCodeEnum;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextInputDialog;
import javafx.scene.image.Image;
import javafx.scene.layout.*;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import java.util.Optional;

public class JavaFXApplication extends Application {
    private CodeDogController codeDogController = SpringUtil.getBean(BeanNameConstant.CODEDOG_CONTROLLER);
    private ShutdownController shutdownController = SpringUtil.getBean(BeanNameConstant.SHUTDOWN_CONTROLLER);
    private Stage primaryStage; // 保存主舞台引用
    private Stage loadingStage; // 用于保存显示“接口调用中”弹窗的Stage引用

    Integer updateCookieErrorNumber = OptionConstant.UPDATE_COOKIE_ERROR_DEFAULT_NUMBER;

    @Override
    public void start(Stage primaryStage) {
        this.primaryStage = primaryStage;
        // 设置主窗口的关闭请求处理事件
        setOnCloseRequest(primaryStage);
        // 主页面布局
        BorderPane mainBorderPane = createMainPage();
        Scene mainScene = new Scene(mainBorderPane, WindowSizeConstant.MAIN_WINDOW_WIDTH, WindowSizeConstant.MAIN_WINDOW_HEIGHT);
        primaryStage.setScene(mainScene);
        addIcons(primaryStage);
        primaryStage.setTitle(WindowTextConstant.MAIN_TITLE);
        primaryStage.show();
    }


    public void addIcons(Stage primaryStage) {
        primaryStage.getIcons().add(new Image(WindowTextConstant.ICON_PATH));
    }

    private BorderPane createMainPage() {
        BorderPane borderPane = new BorderPane();

        // 创建查询作业和查询阶段测按钮
        Button getLessonRecords = new Button(WindowTextConstant.GET_LESSON_RECORDS_BUTTON);
        Button getLessonPaperReports = new Button(WindowTextConstant.GET_LESSON_PAPER_REPORTS_BUTTON);

        // 设置按钮的固定大小
        getLessonRecords.setPrefSize(WindowSizeConstant.SMALL_BUTTON_WIDTH, WindowSizeConstant.SMALL_BUTTON_HEIGHT);
        getLessonPaperReports.setPrefSize(WindowSizeConstant.SMALL_BUTTON_WIDTH, WindowSizeConstant.SMALL_BUTTON_HEIGHT);

        // 设置查询作业按钮的点击事件处理器，点击后跳转到作业详情页面
        getLessonRecords.setOnAction(event -> showLessonRecordsDetailsPage());

        // 设置查询阶段测按钮的点击事件处理器（此处可根据实际需求完善具体逻辑）
        getLessonPaperReports.setOnAction(this::getLessonPaperReports);
        HBox hbox = new HBox(getLessonRecords, getLessonPaperReports);
        hbox.setSpacing(WindowSizeConstant.MIDDLE_SPACING);
        hbox.setAlignment(javafx.geometry.Pos.CENTER);

        borderPane.setCenter(hbox);

        return borderPane;
    }

    private void showLessonRecordsDetailsPage() {
        BorderPane jobDetailsBorderPane = createLessonRecordsDetailsPage();
        Scene jobDetailsScene = new Scene(jobDetailsBorderPane, WindowSizeConstant.LESSON_RECORDS_WINDOW_WIDTH, WindowSizeConstant.LESSON_RECORDS_WINDOW_HEIGHT);
        Stage jobDetailsStage = new Stage();
        addIcons(jobDetailsStage);
        setOnCloseRequest(jobDetailsStage);
        jobDetailsStage.setScene(jobDetailsScene);
        jobDetailsStage.setTitle(WindowTextConstant.GET_LESSON_RECORDS_BUTTON);
        jobDetailsStage.show();

        // 关闭当前主页面（可根据实际需求决定是否隐藏而不是关闭，这里选择关闭示例）
        primaryStage.close();
    }

    private BorderPane createLessonRecordsDetailsPage() {
        BorderPane borderPane = new BorderPane();

        // 创建左上角返回上一层按钮
        Button backButton = new Button(WindowTextConstant.BACK_BUTTON);
        backButton.setOnAction(event -> backToMainPage(event));

        // 创建其他功能按钮
        Button getLessonRecordsByClassButton = new Button(WindowTextConstant.GET_LESSON_RECORDS_BY_CLASS_BUTTON);
        Button getPerformanceButton = new Button(WindowTextConstant.GET_PERFORMANCE_BUTTON);
        Button getLessonRecordsByDateButton = new Button(WindowTextConstant.GET_LESSON_RECORDS_BY_DATE_BUTTON);
        Button getLessonRecordsByTimeSlotButton = new Button(WindowTextConstant.GET_LESSON_RECORDS_BY_TIMESLOT_BUTTON);

        // 设置按钮的固定大小（可根据实际需求调整尺寸）
        backButton.setPrefSize(WindowSizeConstant.SUPER_SMALL_BUTTON_WIDTH, WindowSizeConstant.SUPER_SMALL_BUTTON_HEIGHT);
        getLessonRecordsByClassButton.setPrefSize(WindowSizeConstant.MIDDLE_BUTTON_WIDTH, WindowSizeConstant.MIDDLE_BUTTON_HEIGHT);
        getLessonRecordsByDateButton.setPrefSize(WindowSizeConstant.MIDDLE_BUTTON_WIDTH, WindowSizeConstant.MIDDLE_BUTTON_HEIGHT);
        getLessonRecordsByTimeSlotButton.setPrefSize(WindowSizeConstant.MIDDLE_BUTTON_WIDTH, WindowSizeConstant.MIDDLE_BUTTON_HEIGHT);
        getPerformanceButton.setPrefSize(WindowSizeConstant.MIDDLE_BUTTON_WIDTH, WindowSizeConstant.MIDDLE_BUTTON_HEIGHT);

        // 使用GridPane来实现两行居中对齐布局
        GridPane gridPane = new GridPane();

        gridPane.setHgap(WindowSizeConstant.HGAP); // 设置水平间距
        gridPane.setVgap(WindowSizeConstant.VGAP); // 设置垂直间距

        // 正确设置列约束
        ColumnConstraints column1 = new ColumnConstraints();
        column1.setPercentWidth(WindowSizeConstant.PERCENT_WIDTH);
        ColumnConstraints column2 = new ColumnConstraints();
        column2.setPercentWidth(WindowSizeConstant.PERCENT_WIDTH);
        gridPane.getColumnConstraints().addAll(column1, column2);

        // 正确设置行约束
        RowConstraints row1 = new RowConstraints();
        row1.setPercentHeight(WindowSizeConstant.PERCENT_HEIGHT);
        RowConstraints row2 = new RowConstraints();
        row2.setPercentHeight(WindowSizeConstant.PERCENT_HEIGHT);
        gridPane.getRowConstraints().addAll(row1, row2);
        // 设置列和行的增长优先级（确保在空间有剩余时能均匀扩展来实现居中）
        column1.setHgrow(Priority.ALWAYS);
        column2.setHgrow(Priority.ALWAYS);
        row1.setVgrow(Priority.ALWAYS);
        row2.setVgrow(Priority.ALWAYS);

        // 将按钮添加到GridPane中，实现两行两列的布局
        gridPane.add(getLessonRecordsByClassButton, WindowSizeConstant.COLUMN_INDEX_0, WindowSizeConstant.ROW_INDEX_0);
        gridPane.add(getPerformanceButton, WindowSizeConstant.COLUMN_INDEX_1, WindowSizeConstant.ROW_INDEX_0);
        gridPane.add(getLessonRecordsByDateButton, WindowSizeConstant.COLUMN_INDEX_0, WindowSizeConstant.ROW_INDEX_1);
        gridPane.add(getLessonRecordsByTimeSlotButton, WindowSizeConstant.COLUMN_INDEX_1, WindowSizeConstant.ROW_INDEX_1);

        // 为各个功能按钮添加点击事件处理器
        getLessonRecordsByClassButton.setOnAction(this::getLessonRecordsByClass);
        getPerformanceButton.setOnAction(this::getPerformance);
        getLessonRecordsByDateButton.setOnAction(this::getLessonRecordsByDate);
        getLessonRecordsByTimeSlotButton.setOnAction(this::getLessonRecordsByTimeSlot);

        // 创建一个Pane作为中间容器，用于包裹GridPane并设置其在水平和垂直方向都可扩展
        Pane wrapperPane = new Pane(gridPane);
        wrapperPane.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);

        VBox vbox = new VBox(backButton, wrapperPane);
        vbox.setSpacing(WindowSizeConstant.BIG_SPACING);
//        gridPane.setAlignment(Pos.CENTER);
        borderPane.setCenter(vbox); // 将包含返回按钮和功能按钮的VBox放置在BorderPane的中心区域
        borderPane.setPadding(new Insets(WindowSizeConstant.CENTER_PADDING_PARAM, WindowSizeConstant.CENTER_PADDING_PARAM, WindowSizeConstant.CENTER_PADDING_PARAM, WindowSizeConstant.CENTER_PADDING_PARAM));

        return borderPane;
    }

    // 显示“接口调用中”的不可关闭弹窗
    private void showLoadingDialog() {
        showLoadingDialog(WindowTextConstant.LOADING_ALERT);
    }

    private void showLoadingDialog(String LabelText) {
        loadingStage = new Stage();
        loadingStage.initModality(Modality.APPLICATION_MODAL);
        loadingStage.setTitle(WindowTextConstant.LOADING_TITLE);
        addIcons(loadingStage);
        Label label = new Label(LabelText);
        label.setStyle(WindowTextConstant.LABEL_STYLE);

        VBox vbox = new VBox(label);
        vbox.setAlignment(Pos.CENTER);
        vbox.setSpacing(WindowSizeConstant.SMALL_SPACING);

        Scene scene = new Scene(vbox, WindowSizeConstant.ALERT_WINDOW_WIDTH, WindowSizeConstant.ALERT_WINDOW_HEIGHT);
        loadingStage.setScene(scene);
        loadingStage.show();

        // 设置不可关闭（通过事件过滤，消费掉关闭窗口的事件）
        loadingStage.addEventFilter(WindowEvent.WINDOW_CLOSE_REQUEST, event -> {
            event.consume();
        });
    }

    // 关闭“接口调用中”的弹窗
    private void closeLoadingDialog() {
        if (loadingStage != null) {
            loadingStage.close();
        }
    }

    // 显示“接口调用成功”的可手动关闭弹窗
    private void showSuccessDialog() {
        Stage successStage = new Stage();
        successStage.initModality(Modality.APPLICATION_MODAL);
        successStage.setTitle(WindowTextConstant.RESULT_TITLE);
        addIcons(successStage);
        Label label = new Label(WindowTextConstant.SUCCESS_ALERT);
        label.setStyle(WindowTextConstant.LABEL_STYLE);

        VBox vbox = new VBox(label);
        vbox.setAlignment(Pos.CENTER);
        vbox.setSpacing(WindowSizeConstant.SMALL_SPACING);

        Scene scene = new Scene(vbox, WindowSizeConstant.ALERT_WINDOW_WIDTH, WindowSizeConstant.ALERT_WINDOW_HEIGHT);
        successStage.setScene(scene);
        successStage.show();
    }

    private void showCookieUpdateResultDialog(Integer cookieUpdateResult) {
        Stage successStage = new Stage();
        successStage.initModality(Modality.APPLICATION_MODAL);
        successStage.setTitle(WindowTextConstant.UPDATE_COOKIE_RESULT_TITLE);
        addIcons(successStage);
        if (cookieUpdateResult == ResponseCodeEnum.OK.getCode()) {
            Label label = new Label(WindowTextConstant.UPDATE_COOKIE_SUCCESS_TITLE);
            label.setStyle(WindowTextConstant.LABEL_STYLE);
            VBox vbox = new VBox(label);
            vbox.setAlignment(Pos.CENTER);
            vbox.setSpacing(WindowSizeConstant.SMALL_SPACING);

            Scene scene = new Scene(vbox, WindowSizeConstant.ALERT_WINDOW_WIDTH, WindowSizeConstant.ALERT_WINDOW_HEIGHT);
            successStage.setScene(scene);
            successStage.show();
        } else {
            if (updateCookieErrorNumber <= OptionConstant.UPDATE_COOKIE_ERROR_MAX_NUMBER - 1) {
                updateCookieErrorNumber++;
                updateCookie();
            } else {
                updateCookieErrorNumber = OptionConstant.UPDATE_COOKIE_ERROR_DEFAULT_NUMBER;
                showErrorDialog("Cookie更新失败" + OptionConstant.UPDATE_COOKIE_ERROR_MAX_NUMBER + "次！");
            }
        }
    }

    private void showErrorDialog(String errorStr) {
        Stage errorStage = new Stage();
        errorStage.initModality(Modality.APPLICATION_MODAL);
        errorStage.setTitle(WindowTextConstant.RESULT_TITLE);
        addIcons(errorStage);
        Label label = new Label(errorStr);
        label.setStyle(WindowTextConstant.LABEL_STYLE);

        VBox vbox = new VBox(label);
        vbox.setAlignment(Pos.CENTER);
        vbox.setSpacing(WindowSizeConstant.SMALL_SPACING);

        Scene scene = new Scene(vbox, WindowSizeConstant.ALERT_WINDOW_WIDTH, WindowSizeConstant.ALERT_WINDOW_HEIGHT);
        errorStage.setScene(scene);
        errorStage.show();
    }

    private void getLessonPaperReports(ActionEvent event) {
        showLoadingDialog();
        new Thread(() -> {
            int responseCode = codeDogController.getLessonPaperReports(); // 模拟接口调用，获取返回状态码
            Platform.runLater(() -> {
                closeLoadingDialog();
                if (responseCode == ResponseCodeEnum.OK.getCode()) {
                    showSuccessDialog();
                } else if (responseCode == ResponseCodeEnum.COOKIE_INVALID.getCode()) {
                    updateCookie();
                } else {
                    System.out.println("接口调用失败，状态码: " + responseCode);
                    showErrorDialog(ResponseCodeEnum.getMsgByCode(responseCode));
                }
            });
        }).start();
    }

    private void updateCookie() {
        showCookieUpdateResultDialog(codeDogController.updateCookie(showCookieInputDialog()));
    }

    // 模拟接口调用并处理返回状态码，以handleGetAllDetails为例，其他三个方法同理修改
    private void getLessonRecordsByClass(ActionEvent event) {
        showLoadingDialog(WindowTextConstant.LOADING_LONG_TIME_ALERT);
        new Thread(() -> {
            int responseCode = codeDogController.getLessonRecordsByClass(); // 模拟接口调用，获取返回状态码
            Platform.runLater(() -> {
                closeLoadingDialog();
                if (responseCode == ResponseCodeEnum.OK.getCode()) {
                    showSuccessDialog();
                } else if (responseCode == ResponseCodeEnum.COOKIE_INVALID.getCode()) {
                    updateCookie();
                } else {
                    System.out.println("接口调用失败，状态码: " + responseCode);
                    showErrorDialog(ResponseCodeEnum.getMsgByCode(responseCode));
                }
            });
        }).start();
    }

    // 弹出输入cookie的对话框，并获取用户输入的内容，若用户取消输入则返回null，同时打印出输入的内容
    private String showCookieInputDialog() {
        TextInputDialog dialog = new TextInputDialog();
        dialog.setTitle(WindowTextConstant.COOKIE_TITLE);
        dialog.setHeaderText(WindowTextConstant.COOKIE_HEADER_ALERT);
        dialog.setContentText(WindowTextConstant.COOKIE_CONTENT_ALERT);
        addIcons((Stage) dialog.getDialogPane().getScene().getWindow());
        Optional<String> result = dialog.showAndWait();
        result.ifPresent(System.out::println); // 打印用户输入的内容
        return result.orElse(null);
    }

    // 弹出输入日期的对话框，并获取用户输入的内容，若用户取消输入则返回null，同时打印出输入的内容
    private String showDateInputDialog() {
        TextInputDialog dialog = new TextInputDialog();
        dialog.setTitle(WindowTextConstant.DATE_TITLE);
        dialog.setHeaderText(WindowTextConstant.DATE_HEADER_ALERT);
        dialog.setContentText(WindowTextConstant.DATE_CONTENT_ALERT);
        addIcons((Stage) dialog.getDialogPane().getScene().getWindow());
        Optional<String> result = dialog.showAndWait();
        result.ifPresent(System.out::println); // 打印用户输入的内容
        return result.orElse(null);
    }

    // 弹出输入时间的对话框，并获取用户输入的内容，若用户取消输入则返回null，同时打印出输入的内容
    private String showTimeSlotInputDialog() {
        TextInputDialog dialog = new TextInputDialog();
        dialog.setTitle(WindowTextConstant.TIME_SLOT_TITLE);
        dialog.setHeaderText(WindowTextConstant.TIME_SLOT_HEADER_ALERT);
        dialog.setContentText(WindowTextConstant.TIME_SLOT_CONTENT_ALERT);
        addIcons((Stage) dialog.getDialogPane().getScene().getWindow());
        Optional<String> result = dialog.showAndWait();
        result.ifPresent(System.out::println); // 打印用户输入的内容
        return result.orElse(null);
    }

    private void getLessonRecordsByDate(ActionEvent event) {
        String dateStr = showDateInputDialog();
        showLoadingDialog();
        new Thread(() -> {
            int responseCode = codeDogController.getLessonRecordsByDate(dateStr);
            Platform.runLater(() -> {
                closeLoadingDialog();
                if (responseCode == ResponseCodeEnum.OK.getCode()) {
                    showSuccessDialog();
                } else if (responseCode == ResponseCodeEnum.COOKIE_INVALID.getCode()) {
                    updateCookie();
                } else {
                    System.out.println("接口调用失败，状态码: " + responseCode);
                    showErrorDialog(ResponseCodeEnum.getMsgByCode(responseCode));
                }
            });
        }).start();
    }

    private void getLessonRecordsByTimeSlot(ActionEvent event) {
        String timeSlotStr = showTimeSlotInputDialog();
        showLoadingDialog();
        new Thread(() -> {
            int responseCode = codeDogController.getLessonRecordsByTimeSlot(timeSlotStr);
            Platform.runLater(() -> {
                closeLoadingDialog();
                if (responseCode == ResponseCodeEnum.OK.getCode()) {
                    showSuccessDialog();
                } else if (responseCode == ResponseCodeEnum.COOKIE_INVALID.getCode()) {
                    updateCookie();
                } else {
                    System.out.println("接口调用失败，状态码: " + responseCode);
                    showErrorDialog(ResponseCodeEnum.getMsgByCode(responseCode));
                }
            });
        }).start();
    }

    private void getPerformance(ActionEvent event) {
        showLoadingDialog(WindowTextConstant.LOADING_LONG_TIME_ALERT);
        new Thread(() -> {
            int responseCode = codeDogController.getPerformance();
            Platform.runLater(() -> {
                closeLoadingDialog();
                if (responseCode == ResponseCodeEnum.OK.getCode()) {
                    showSuccessDialog();
                } else if (responseCode == ResponseCodeEnum.COOKIE_INVALID.getCode()) {
                    updateCookie();
                } else {
                    System.out.println("接口调用失败，状态码: " + responseCode);
                    showErrorDialog(ResponseCodeEnum.getMsgByCode(responseCode));
                }
            });
        }).start();
    }

    private void backToMainPage(Event event) {
        // 获取最初的主页面布局（BorderPane）
        BorderPane mainBorderPane = createMainPage();
        Scene mainScene = new Scene(mainBorderPane, WindowSizeConstant.MAIN_WINDOW_WIDTH, WindowSizeConstant.MAIN_WINDOW_HEIGHT);

        // 复用最初的primaryStage，设置新的场景，实现返回主页面效果
        primaryStage.setScene(mainScene);
        primaryStage.show();

        Button clickedButton = (Button) event.getSource();
        Scene currentScene = clickedButton.getScene();
        Stage currentStage = (Stage) currentScene.getWindow();
        currentStage.close();
    }

    // 新增方法：用于触发Spring Boot项目关闭，通过JMX通知Spring Boot中的ShutdownController执行关闭操作
    private void triggerSpringBootShutdown() {
        shutdownController.shutDownContext();
    }

    public static void main(String[] args) {
        launch(args);
    }

    /**
     * 设置监听事件，关闭窗口，停止Spring boot项目
     *
     * @param primaryStage
     */
    public void setOnCloseRequest(Stage primaryStage) {
        // 设置主窗口的关闭请求处理事件
        primaryStage.setOnCloseRequest(event -> {
            try {
                triggerSpringBootShutdown();
            } catch (Exception e) {
                System.err.println("关闭Spring Boot项目时出错: " + e.getMessage());
            }
        });
    }
}